"use strict";
//装饰器
// 装饰器是一种特殊类型的声明，它能够被附加到类声明，方法， 访问符，属性或参数上，来扩展他们的功能；
//通俗来讲装饰器就是一个方法，可以注入到类，方法等里面，拓展他们的功能
// 装饰器使用 @expression这种形式，expression求值后必须为一个函数，它会在运行时被调用，被装饰的声明信息做为参数传入。
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
// 类装饰器
//定义装饰器
function logClass(params) {
    //原型上扩展方法
    params.prototype.apiUrl = () => {
        console.log('我是装饰器');
    };
    //扩展属性
    params.prototype.run = '我是属性';
}
//普通写法，无法传参
let Person = class Person {
    constructor() {
    }
};
Person = __decorate([
    logClass
], Person);
//实例化
let p = new Person();
p.apiUrl(); //我是装饰器
console.log(p.run); //我是属性
// 第二种写法，可传参
function myClass(str) {
    return (params) => {
        params.prototype.massega = str;
    };
}
let Son = class Son {
    constructor() {
    }
};
Son = __decorate([
    myClass('我是传参的')
], Son);
//实例化
let s = new Son();
console.log(s.massega);
//类装饰器不仅能扩展类的方法等，还能重载构造函数，和重写它的属性方法等
function Mylog(params) {
    return class extends params {
        constructor() {
            super(...arguments);
            //重写属性
            this.api = '我是程凯';
        }
        //重写方法
        sayName() {
            console.log('我是重写方法' + this.api);
        }
    };
}
let Repeat = class Repeat {
    constructor() {
        this.api = '我是谁';
    }
    sayName() {
        console.log(this.api);
    }
};
Repeat = __decorate([
    Mylog
], Repeat);
let r = new Repeat();
console.log(r.api); //我是程凯
r.sayName(); //我是重写方法我是程凯
// 属性装饰器
/*
属性装饰器会在运行时当做函数被调用，传入以下两个参数,(注意是运行不是实例化)
    1：对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
    2：成员的名字
*/
function myCru(params) {
    return (target, str) => {
        target[str] = params;
    };
}
class Cru {
    sayName() {
        console.log(this.sex);
    }
}
__decorate([
    myCru('我是属性装饰器')
], Cru.prototype, "sex", void 0);
let c = new Cru();
c.sayName(); //我是属性装饰器
//装饰器在这里调用的时候是在运行的时候，而不是在实例化的时候
// 方法装饰器
/*
他会被应用到方法的属性描述符上面，可以修改，监视，修改或者替换方法定义
方法装饰器会在运行时传入下列三个参数
    1：对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
    2：成员的名字
    3：成员的属性描述符
*/
function get(str) {
    //接受三个参数
    return (target, method, desc) => {
        //扩展它的一个属性
        target.age = '三笠';
        target.method = () => {
            console.log('我是扩展那个方法');
        };
        //保存以前的方法
        let oldmet = desc.value;
        //修改以前的方法
        desc.value = function (...args) {
            // 调用以前的方法，传入修改后的参数
            oldmet('我是修改之后的');
        };
    };
}
class Http {
    sayNmae(str) {
        console.log(str);
    }
}
__decorate([
    get('我是方法装饰器')
], Http.prototype, "sayNmae", null);
let h = new Http();
console.log(h.age); //三笠
h.method(); //我是扩展那个方法
h.sayNmae(); //
// 方法参数装饰器
/*
这个表达式会在函数被调用时调用，可以为类的原型增加一些源数据
方法装饰器会在运行时传入下列三个参数
    1：对于静态成员来说是类的构造函数，对于实例成员是类的原型对象
    2：方法的名字
    3：参数在函数参数列表中的索引
*/
function myGet(str) {
    //接受三个参数
    return (target, method, index) => {
        console.log(target);
        console.log(method);
        console.log(index);
        target.apiUrl = str;
    };
}
class Mycl {
    sayname(utill) {
    }
}
__decorate([
    __param(0, myGet('参数装饰器'))
], Mycl.prototype, "sayname", null);
let m = new Mycl();
console.log(m.apiUrl); //参数装饰器
// 装饰器的执行顺序
function log1(params) {
    return (target) => {
        console.log(params);
    };
}
function log2(params) {
    return (target) => {
        console.log(params);
    };
}
function atter1(params) {
    return (target, name) => {
        console.log(params);
    };
}
function mthods(params) {
    return (target, name) => {
        console.log(params);
    };
}
function paramsLog1(params) {
    return (target, method, index) => {
        console.log(params);
    };
}
function paramsLog2(params) {
    return (target, name, desc) => {
        console.log(params);
    };
}
let Logs = class Logs {
    getData() {
        return true;
    }
    params(ut1, ut2) {
    }
};
__decorate([
    atter1('-------我是属性装饰器1')
], Logs.prototype, "apiUrl", void 0);
__decorate([
    mthods('我是方法装饰器')
], Logs.prototype, "getData", null);
__decorate([
    __param(0, paramsLog1('我是方法参数装饰器1')),
    __param(1, paramsLog2('我是方法参数装饰器2'))
], Logs.prototype, "params", null);
Logs = __decorate([
    log1('我是类装饰器1'),
    log2('我是类装饰器2')
], Logs);
let l = new Logs();
//执行顺序
// 属性>方法>方法参数>类装饰器
//如果有多个同样的装饰器，他会先执行后面的
